#pragma comment(lib,"openal32.lib")
#pragma comment(lib,"alut.lib")
#pragma comment(lib,"EFX-Util.lib")

#include <stdlib.h> 
#include <stdio.h>

#include "Framework.h"
#include "EFX-Util.h"
#include <math.h>
#include <AL\alut.h>

#include <fstream>
#include <iostream>
#include <conio.h>

#define M_PI       3.14159265358979323846

static double frequencyBuffer1 = 440.0;
static double frequencyBuffer2 = 587.0;
static double frequencyBuffer3 = 660.0;
static unsigned int amountWaveRepeat = 100;

static void reportAlutError (void) {
	fprintf (stderr, "ALUT error: %s\n", alutGetErrorString (alutGetError ())); 
}


short* generateSine(double frequency, double seconds, unsigned int sampleRate, unsigned int& bufferSize) {
	bufferSize = (unsigned int)((seconds * sampleRate) + 0.5); // +0.5 for rounding rather than the int-convert typical floor()
	bufferSize *= 2;
	short* samples = new short[bufferSize];

	for( unsigned int i = 0; i < bufferSize; ++i ) {
		samples[i] = ((short)(0x7FFF * sin( (2.0f*float(M_PI)*frequency)/sampleRate * i )));
	}
	
	return samples;
}


int main(int argc, char **argv) 
{ 
	int option = 2;

	ALuint soundBuffer[3];
	ALuint soundSource[3]; 

	if ( alutInit (&argc, argv) == AL_FALSE ) {
		reportAlutError();
		return EXIT_FAILURE;
	}

	if ( !ALFWIsEFXSupported() ) { // initialize EFX extensions
		return EXIT_FAILURE;
	}

	

	alGenBuffers(3, &soundBuffer[0]);
	unsigned int bufferSize[3];
	short* s440 = generateSine(frequencyBuffer1, ((double)(frequencyBuffer1*amountWaveRepeat)/44000.0), 44000, bufferSize[0]);
	short* s587 = generateSine(frequencyBuffer2, ((double)(frequencyBuffer2*amountWaveRepeat)/44000.0), 44000, bufferSize[1]);
	short* s660 = generateSine(frequencyBuffer3, ((double)(frequencyBuffer3*amountWaveRepeat)/44000.0), 44000, bufferSize[2]);


	// load in OpenAL
	alBufferData(soundBuffer[0], AL_FORMAT_MONO16, s440, bufferSize[0], 44000);
	alBufferData(soundBuffer[1], AL_FORMAT_MONO16, s587, bufferSize[1], 44000);
	alBufferData(soundBuffer[2], AL_FORMAT_MONO16, s660, bufferSize[2], 44000);

	// generate a "source", essentially a "slot" audio can be assigned to, modified, and played from
	alGenSources (3, &soundSource[0]); 
	// assign the loaded buffer to the source
	alSourcei(soundSource[0], AL_BUFFER, soundBuffer[0]); 
	alSourcei(soundSource[1], AL_BUFFER, soundBuffer[1]); 
	alSourcei(soundSource[2], AL_BUFFER, soundBuffer[2]); 
	
	// loop on
	alSourcei(soundSource[0], AL_LOOPING, AL_TRUE);
	alSourcei(soundSource[1], AL_LOOPING, AL_TRUE);
	alSourcei(soundSource[2], AL_LOOPING, AL_TRUE);
	alSourcef(soundSource[0], AL_GAIN, 0.33f);
	alSourcef(soundSource[1], AL_GAIN, 0.33f);
	alSourcef(soundSource[2], AL_GAIN, 0.33f);

	// play the source
	std::cout << "playing source 0 (" << frequencyBuffer1 << "Hz)" << std::endl;
	alSourcePlay (soundSource[0]); 
	alutSleep (1); 
	std::cout << "playing source 1 (" << frequencyBuffer2 << "Hz)" << std::endl;
	alSourcePlay (soundSource[1]); 
	alutSleep (1); 
	std::cout << "playing source 2 (" << frequencyBuffer3 << "Hz)" << std::endl;
	alSourcePlay (soundSource[2]); 
	alutSleep (2); 
	// stop the source
	alSourceStop(soundSource[0]);
	alSourceStop(soundSource[1]);
	alSourceStop(soundSource[2]);
	// delete it
	alDeleteSources(3, &soundSource[0]);
	alDeleteBuffers(3, &soundBuffer[0]);

	delete[] s440;
	delete[] s587;
	delete[] s660;

	alutExit (); 
	return EXIT_SUCCESS; 
}